package com.ecloud.support.generator.service.impl;

import java.io.Serializable;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.time.LocalDateTime;
import java.util.List;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ecloud.common.base.result.Result;
import com.ecloud.common.base.result.ResultBuilder;
import com.ecloud.common.base.result.ResultStatus;
import com.ecloud.common.base.result.RowsBuilder;
import com.ecloud.common.data.annotation.DynamicDS;
import com.ecloud.common.data.dynamic.DynamicDataSource;
import com.ecloud.common.utils.check.LongUtils;
import com.ecloud.common.utils.check.StringUtils;
import com.ecloud.common.utils.code.UUIDUtil;
import com.ecloud.support.generator.custom.DatabaseEnum;
import com.ecloud.support.generator.mapper.DbConfigMapper;
import com.ecloud.support.generator.model.convert.DbConfigConverter;
import com.ecloud.support.generator.model.dto.DbConfigDto;
import com.ecloud.support.generator.model.entity.DbConfigPo;
import com.ecloud.support.generator.model.vo.DbConfigVo;
import com.ecloud.support.generator.service.iface.IDbConfigService;
import com.ecloud.support.generator.service.iface.ITemplateService;
import com.ecloud.support.generator.service.iface.ITemplateSetService;

/**
 * DbConfigService
 *
 * @author LiuGangQiang Create in 2021/04/15
 */
@Service
@DynamicDS
public class DbConfigService extends ServiceImpl<DbConfigMapper, DbConfigPo> implements IDbConfigService {
    private final static Logger LOGGER = LoggerFactory.getLogger(DbConfigService.class);
    @Resource
    private DynamicDataSource dynamicDataSource;
    @Resource
    private ITemplateService templateService;
    @Resource
    private ITemplateSetService templateSetService;

    /**
     * @see com.ecloud.support.generator.service.iface.IDbConfigService#test(com.ecloud.support.generator.model.dto.DbConfigDto)
     */
    @Override
    public Result<?> test(DbConfigDto dto) {
        try {
            Class.forName(dto.getDriver());
            Connection connection = DriverManager.getConnection(dto.getUrl(), dto.getUsername(), dto.getPassword());
            if (connection != null) {
                connection.close();
                return ResultBuilder.build(ResultStatus.OK);
            }
            return ResultBuilder.build(ResultStatus.FAIL).setKey("dbconfig.connection.test.fail");
        } catch (ClassNotFoundException | SQLException e) {
            LOGGER.error("connect database [{}] error", dto.getDriver());
            return ResultBuilder.build(ResultStatus.FAIL).setKey("dbconfig.connection.test.fail");
        }
    }

    /**
     * @see com.ecloud.support.generator.service.iface.IDbConfigService#insert(com.ecloud.support.generator.model.dto.DbConfigDto)
     */
    @Override
    public Result<?> insert(DbConfigDto dto) {
        /* 判断数据库是否存在记录 */
        LambdaQueryWrapper<DbConfigPo> queryWrapper = new QueryWrapper<DbConfigPo>().lambda();
        queryWrapper.select(DbConfigPo::getId);
        queryWrapper.eq(DbConfigPo::getDbName, dto.getDbName());
        queryWrapper.eq(DbConfigPo::getDbType, dto.getDbType());
        if (this.getOne(queryWrapper) != null) {
            return ResultBuilder.build(ResultStatus.CONFLICT).setKey("dbconfig.name.conflict", dto.getDbName());
        }
        /* 不存在执行新增 */
        dto.setId(UUIDUtil.uuid());
        /* 设置驱动路径 */
        dto.setDriver(DatabaseEnum.fromType(dto.getDbType()).getDriver());
        dto.setCreateTime(LocalDateTime.now());
        DbConfigPo po = DbConfigConverter.INSTANCE.dtoToPo(dto);
        if (this.save(po)) {
            return ResultBuilder.build(ResultStatus.OK);
        }
        return ResultBuilder.build(ResultStatus.FAIL);
    }

    /**
     * @see com.ecloud.support.generator.service.iface.IDbConfigService#delete(com.ecloud.support.generator.model.dto.DbConfigDto)
     */
    @Override
    public Result<?> delete(DbConfigDto dto) {
        /* 判断数据库是否存在记录 */
        LambdaQueryWrapper<DbConfigPo> queryWrapper = new QueryWrapper<DbConfigPo>().lambda();
        queryWrapper.eq(DbConfigPo::getId, dto.getId());
        queryWrapper.select(DbConfigPo::getId);
        if (this.getOne(queryWrapper) == null) {
            return ResultBuilder.build(ResultStatus.DATA_NOT_FOUND).setKey("dbconfig.id.not.found", dto.getId());
        }
        /* 存在执行删除 */
        if (this.remove(queryWrapper)) {
            dynamicDataSource.delDataSource(dto.getId());
            return ResultBuilder.build(ResultStatus.OK);
        }
        return ResultBuilder.build(ResultStatus.FAIL);
    }

    /**
     * @see com.ecloud.support.generator.service.iface.IDbConfigService#update(com.ecloud.support.generator.model.dto.DbConfigDto)
     */
    @Override
    public Result<?> update(DbConfigDto dto) {
        /* 判断数据库是否存在记录 */
        LambdaQueryWrapper<DbConfigPo> queryWrapper = new QueryWrapper<DbConfigPo>().lambda();
        queryWrapper.select(DbConfigPo::getId);
        queryWrapper.eq(DbConfigPo::getId, dto.getId());
        if (this.getOne(queryWrapper) == null) {
            return ResultBuilder.build(ResultStatus.DATA_NOT_FOUND).setKey("dbconfig.id.not.found", dto.getId());
        }

        /* 判断修改的数据是否存在冲突 */
        LambdaQueryWrapper<DbConfigPo> uniqueWrapper = new QueryWrapper<DbConfigPo>().lambda();
        uniqueWrapper.ne(DbConfigPo::getId, dto.getId());
        uniqueWrapper.eq(DbConfigPo::getDbName, dto.getDbName());
        uniqueWrapper.eq(DbConfigPo::getDbType, dto.getDbType());
        queryWrapper.select(DbConfigPo::getId);
        if (this.getOne(uniqueWrapper) != null) {
            return ResultBuilder.build(ResultStatus.CONFLICT).setKey("dbconfig.name.conflict", dto.getDbName());
        }

        /* 修改数据 */
        LambdaUpdateWrapper<DbConfigPo> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(DbConfigPo::getId, dto.getId());
        /* 存在执行修改 */
        DbConfigPo po = DbConfigConverter.INSTANCE.dtoToPo(dto);
        if (this.update(po, updateWrapper)) {
            dynamicDataSource.delDataSource(dto.getId());
            return ResultBuilder.build(ResultStatus.OK);
        }
        return ResultBuilder.build(ResultStatus.FAIL);
    }

    /**
     * @see com.ecloud.support.generator.service.iface.IDbConfigService#queryList(com.ecloud.support.generator.model.dto.DbConfigDto)
     */
    @Override
    public Result<?> queryList(DbConfigDto dto) {
        /* 构造查询条件 */
        LambdaQueryWrapper<DbConfigPo> queryWrapper = new QueryWrapper<DbConfigPo>().lambda();
        queryWrapper.eq(StringUtils.isNotBlank(dto.getDbType()), DbConfigPo::getDbType, dto.getDbType());
        queryWrapper.and(StringUtils.isNotBlank(dto.getKeyword()),
                wrapper -> wrapper.like(DbConfigPo::getDbName, dto.getKeyword())
                        .or()
                        .like(DbConfigPo::getDbType, dto.getKeyword())
                        .or()
                        .like(DbConfigPo::getUsername, dto.getKeyword())
                        .or()
                        .like(DbConfigPo::getSchema, dto.getKeyword()));
        queryWrapper.orderByAsc(DbConfigPo::getCreateTime);
        /* 构造分页查询 */
        IPage<DbConfigPo> page = this.page(new Page<>(dto.getPage(), dto.getRows()), queryWrapper);
        if (LongUtils.isGtZero(page.getTotal())) {
            /* 转换 */
            List<DbConfigVo> pos = DbConfigConverter.INSTANCE.poToVo(page.getRecords());
            return ResultBuilder.build(ResultStatus.OK, RowsBuilder.build(page.getTotal(), pos));
        }
        return ResultBuilder.build(ResultStatus.DATA_NOT_FOUND, RowsBuilder.build());
    }

    /**
     * @see com.baomidou.mybatisplus.extension.service.IService#getById(java.io.Serializable)
     */
    @Override
    public DbConfigPo getById(Serializable id) {
        return super.getById(id);
    }
}
